# coding=utf-8

from ..ToolsConfig import *


def RegisterSystemFastly(api, cls):
    """
    快速注册系统
    :param api:serverApi or clientApi
    :param cls:系统类
    :return:
    """
    api.RegisterSystem(
        MOD_NAME, cls.__name__,
        '{}.{}'.format(cls.__module__, cls.__name__)
    )


class SystemTools(object):
    """
    系统工具箱,以不同类进行分辨
    """
    classFunc = []

    @classmethod
    def Binding(cls, ModName='', ModVersion=''):
        """
        绑定系统类
        :param ModName:模组名称
        :param ModVersion:模组版本
        :return:
        """

        def binding(systemCls):
            tag = systemCls.__name__ + ModName + ModVersion
            if tag not in CREATED_TOOLS:
                CREATED_TOOLS[tag] = cls(systemCls)
            else:
                CREATED_TOOLS[tag].Relisten()
            return systemCls

        return binding

    @staticmethod
    def CreateListener(namespace, systemName):
        """
        创建固定系统的监听函数.拿到函数后使用方法与ListenForEvent相同但不需要传入namespace和systemName参数
        :param namespace:需要监听的系统namespace
        :param systemName:需要监听的系统systemName
        :return:
        """

        def Listener(eventName=None, priority=0):
            def Listen(func):
                funcName = func.__name__
                EventName = [namespace, systemName, eventName if eventName else funcName, 0, func, priority]
                if EventName not in SystemTools.classFunc:
                    SystemTools.classFunc.append(EventName)
                return func

            return Listen

        return Listener

    @staticmethod
    def ListenForEvent(eventName=None, namespace=MC_SYSTEM_NAMESPACE, systemName=MC_SYSTEM_NAME, priority=0):
        """
        监听事件,binding的服务端可监听服务端事件,binding的客户端则可监听客户端事件
        :param eventName: 可选:事件名 or 不传入参数.若不传入参数,则将函数名称视为事件名称
        :param namespace:如果需要监听其他系统内的事件,需要传入系统的namespace
        :param systemName:如果需要监听其他系统内的事件,需要传入系统的systemName
        :param priority:执行优先级
        :return:
        """

        def Listen(func):
            funcName = func.__name__
            EventName = [namespace, systemName, eventName if eventName else funcName, 0, func, priority]
            if EventName not in SystemTools.classFunc:
                SystemTools.classFunc.append(EventName)
            return func

        return Listen

    def __init__(self, cls):
        self.systemCls = cls
        self.InitSystemOriginal = self.systemCls.__init__
        setattr(self.systemCls, '__init__', self.InitInstead())
        self.bindingInstance = None

    def Relisten(self):
        for args in SystemTools.classFunc:
            args[3] = self.bindingInstance
            self.bindingInstance.UnListenForEvent(*args)
            self.bindingInstance.ListenForEvent(*args)
            args[3] = 0

    def __Listen(self):
        if self.bindingInstance:
            for args in SystemTools.classFunc:
                args[3] = self.bindingInstance
                if hasattr(self.bindingInstance, args[4].__name__):
                    self.bindingInstance.ListenForEvent(*args)
                args[3] = 0

    def InitInstead(self):
        def __init__(systemInstance, namespace, systemName, self=self):
            self.InitSystemOriginal(systemInstance, namespace, systemName)
            if systemInstance.__class__ is self.systemCls:
                self.bindingInstance = systemInstance
                self.__Listen()

        return __init__
